#!/usr/bin/env python
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

__licence__ = "GPLv2"
__copyright__ = "2008, Matt Layman"
__author__ = "Matt Layman <laymansterms.dev@gmail.com>"

import unittest
import sys
import os

sys.path += [os.path.abspath('..')]

from tests.Music_test import TestMusic

from frontend.medialibrary.music import Track, TrackTypeError
from frontend.medialibrary.music import TrackRatingOutOfRange
from frontend.medialibrary.music import Album, AlbumHasNoTracks
from frontend.medialibrary.playable import Playable

class TestTrack(TestMusic):
    
    def setUp(self):
        TestMusic.setUp(self)
        self.track = Track('/path/to/track.mp3', # filename
                           'title',
                           1, # tracknumber
                           'artist0',
                           'album0',
                           'genre',
                           '128', # bitrate
                           2008, # year
                           5, # rating
                           240, # length
                           'comment',
                           'lyrics')
        
    def tearDown(self):
        TestMusic.tearDown(self)

    def testTrackConstructor(self):
        """testTrackConstructor - Ensures that a Track object is created"""
        self.assertTrue(isinstance(self.track, Track))
        
    def testTrackBadConstructor(self):
        """testTrackBadConstructor - Ensures that bad track construction
        raises an exception for the integer fields"""
        for i in [2, 7, 8, 9]:
            t = ['a', 'b', 1, 'c', 'd', 'e', 'f', 2, 3, 4, 'g', 'h']
            t[i] = str(t[i])
            self.assertRaises(TrackTypeError, Track, t[0], t[1], t[2], t[3],
                              t[4], t[5], t[6], t[7], t[8], t[9], t[10], t[11])

    def testTrackRatingInRange(self):
        """testTrackRatingInRange - Ensures that the ratings in range create
        valid Track objects"""
        for i in range(1,6):
            self.track = Track('a', 'b', 1, 'c', 'd', 'e', 'f', 2, i, 3, 'g',
                               'h')
            self.assertTrue(isinstance(self.track, Track))
            self.assertEqual(self.track.get_rating(), i)                   
            
    def testTrackRatingOutOfRange(self):
        """testTrackRatingOutOfRange - Ensures that the rating raises an
        exception for something out of range in construction"""
        for i in [0, 6]:
            self.assertRaises(TrackRatingOutOfRange, Track, 'a', 'b', 1, 'c',
                              'd', 'e', 'f', 2, i, 3, 'g', 'h')

    def testTrackGetFilename(self):
        """testTrackGetFilename - Ensures that the filename is returned"""
        result = self.track.get_filename()
        self.assertEqual(result, '/path/to/track.mp3')
        
    def testTrackGetTitle(self):
        """testTrackGetTitle - Ensures that the title is returned"""
        result = self.track.get_title()
        self.assertEqual(result, 'title')
        
    def testTrackGetTrackNumber(self):
        """testTrackGetTrackNumber - Ensures that the tracknumber is
        returned"""
        result = self.track.get_tracknumber()
        self.assertEqual(result, 1)
        
    def testTrackGetArtist(self):
        """testTrackGetArtist - Ensures that the artist is returned"""
        result = self.track.get_artist()
        self.assertEqual(result, 'artist0')
        
    def testTrackGetAlbum(self):
        """testTrackGetAlbum - Ensures that an album object is returned"""
        result = self.track.get_album(self.cursor)
        self.assertTrue(isinstance(result, Album))
        self.assertEqual(result.get_title(), 'album0')
        
    def testTrackGetAlbumNot(self):
        """testTrackGetAlbumNot - Ensures that a bad album in the track
        returns AlbumHasNoTracks"""
        self.badTrack = Track('path', 'title', 1, 'artist',
                              'foo-bar-baz**', # Here is the bad input
                              'genre', '128', 2008, 5, 240, 'comment',
                              'lyrics')
        self.assertRaises(AlbumHasNoTracks, self.badTrack.get_album,
                          self.cursor)
        
    def testTrackGetAlbumArtUrlExists(self):
        """testTrackGetAlbumArtUrl - Ensures that the album art url is
        returned"""
        album_art = os.path.join(self.art_path, "artist0 - album0.jpg")
        file = open(album_art, "wb")
        file.close()
        result = self.track.get_album_art_url(self.cursor)
        self.assertEqual(result, album_art)
        if os.path.exists(album_art):
            os.remove(album_art)
            
    def testTrackGetAlbumArtUrlNotExists(self):
        """testTrackGetAlbumArtUrlNotExists - Ensures that when art does
        not exist, None is returned"""
        album_art = os.path.join(self.art_path, "artist0 - album0.jpg")
        result = self.track.get_album_art_url(self.cursor)
        self.assertEqual(result, None)
        
    def testTrackGetGenre(self):
        """testTrackGetGenre - Ensures that the genre is returned"""
        result = self.track.get_genre()
        self.assertEqual(result, 'genre')
        
    def testTrackGetBitrate(self):
        """testTrackGetBitrate - Ensures that the bitrate is returned"""
        result = self.track.get_bitrate()
        self.assertEqual(result, '128')
        
    def testTrackGetYear(self):
        """testTrackGetYear - Ensures that the year is returned"""
        result = self.track.get_year()
        self.assertEqual(result, 2008)
    
    def testTrackGetRating(self):
        """testTrackGetRating - Ensures that the rating is returned"""
        result = self.track.get_rating()
        self.assertEqual(result, 5)
        
    def testTrackGetLength(self):
        """testTrackGetLength - Ensures that the length is returned"""
        result = self.track.get_length()
        self.assertEqual(result, 240)
        
    def testTrackGetComment(self):
        """testTrackGetComment - Ensures that the comment is returned"""
        result = self.track.get_comment()
        self.assertEqual(result, 'comment')

    def testTrackFetchLyrics(self):
        """testTrackFetchLyrics - Ensures that lyrics fetching is correctly
        handled by LyricsDownloader"""
        #TODO: write this test, how do you mock the LyricsDownloader that is
        # interal to this function?
        pass
    
    def testTrackFetchLyricsNoCallback(self):
        """testTrackFetchLyricsNoCallback - Ensures lyrics are at least set
        when no callback function is entered"""
        #TODO: write this test
        pass
        
    def testTrackGetLyrics(self):
        """testTrackGetLyrics - Ensures that the lyrics are returned"""
        result = self.track.get_lyrics()
        self.assertEqual(result, 'lyrics')
        
    def testTrackSetLyrics(self):
        """testTrackSetLyrics - Ensures that lyrics are properly set"""
        self.track.set_lyrics('some new lyrics')
        self.assertEqual(self.track.get_lyrics(), 'some new lyrics')
        
    def testTrackSetNoneLyrics(self):
        """testTrackSetNoneLyrics - Ensures that lyrics are set to empty
        string when None is passed as lyrics input"""
        self.track.set_lyrics(None)
        self.assertEqual(self.track.get_lyrics(), '')
        
    def testTrackGetType(self):
        """testTrackGetType - Ensures that the type is returned"""
        result = self.track.get_type()
        self.assertEqual(result, Playable.AUDIO_STREAM)
    
    def testTrackGetUri(self):
        """testTrackGetUri - Ensures that the uri is returned"""
        result = self.track.get_uri()
        self.assertEqual(result, 'file:///path/to/track.mp3')
        